﻿using Basic.Base.CustomAttribute;
using Newtonsoft.Json;
using System.ComponentModel;

namespace System
{
    public static class EnumExtension
    {
        private static ConcurrentDictionary<Guid, List<EnumItem>> EnumInfoDict = new ConcurrentDictionary<Guid, List<EnumItem>>();

        public static string GetDescription(this Enum value)
        {
            var attr = value.GetType().GetField(value.ToString())?.GetCustomAttribute<DescriptionAttribute>();
            return attr?.Description;
        }
        public static EnumInfoAttribute GetEnumItem(this Enum value)
        {
            var cusAttr = value.GetType().GetField(value.ToString())?.GetCustomAttribute<EnumInfoAttribute>();
            return cusAttr;

        }

        public static List<EnumItem> GetEnumItems<T>() where T : struct, Enum
        {
            Type enumType = typeof(T);

            if (EnumInfoDict.TryGetValue(enumType.GUID, out var list))
                return list;

            var result = new List<EnumItem>();
            T[] array = Enum.GetValues<T>();
            return array.GetEnumItems();
        }


        public static List<EnumItem> GetEnumItems<T>(this T[] values) where T : struct, Enum
        {
            Type enumType = typeof(T);

            var result = new List<EnumItem>();
            T[] array = values;
            foreach (var item in array)
            {
                var enumInfo = item.GetEnumItem();
                var enumItem = new EnumItem
                {
                    Text = item.ToString(),
                    Value = Convert.ToInt64(Enum.Parse(enumType, item.ToString())),
                    Descprtion = item.GetDescription(),
                };
                if (enumInfo != null)
                {
                    enumItem.Descprtion ??= enumInfo.Description;
                    enumItem.TextName = enumInfo.TextName;
                }
                else
                {
                    enumItem.TextName = item.GetDescription();
                }
                result.Add(enumItem);
            }
            EnumInfoDict.TryAdd(enumType.GUID, result);
            return result;
        }

        public static EnumItem GetEnum<T>(this T value) where T : struct, Enum
        {
            var attr = value.GetEnumItem();
            return new EnumItem
            {
                Text = value.ToString(),
                Value = Convert.ToInt64(Enum.Parse(value.GetType(), value.ToString())),
                Descprtion = value.GetDescription() ?? attr?.Description,
                TextName = attr?.TextName ?? value.GetDescription()
            };
        }

    }

    public sealed class EnumItem
    {
        public string Text { get; set; }
        public long Value { get; set; }
        public string TextName { get; set; }
        public string Descprtion { get; set; }

        public override int GetHashCode()
        {
            return Value.GetHashCode();
        }

        public override string ToString() => JsonConvert.SerializeObject(this);

        public override bool Equals(object? obj)
        {
            var enObj = obj as EnumItem;
            if (enObj == null)
                return false;
            return string.Equals(Text, enObj.Text) && Value == enObj.Value && string.Equals(TextName, enObj.TextName) && string.Equals(Descprtion, enObj.Descprtion);
        }
    }

}